package edu.hawaii.wattdepotapps;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.apache.wicket.protocol.http.WicketServlet;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.ServletHolder;
import org.wattdepot.client.WattDepotClient;
import edu.hawaii.wattdepotapps.monitor.MonitorPage;
import edu.hawaii.wattdepotapps.visualizer.VisualizationPage;

/**
 * Enables WattDepot Web Applications to run inside the Jetty container.
 * 
 * @author Edward Meyer, Kendyll Doi, Bao Huy Ung
 * @version 2.0
 */
public class Jetty {

  /** The port used by this web application. */
  private static int port = 8003;
  /** The context root. */
  private static String contextPath = "wattdepotapps";
  /** The class corresponding to this web application. */
  private static String applicationClass = "edu.hawaii.wattdepotapps.WattDepotApplications";

  /**
   * Starts up Jetty and points it at Wicket. This method does not return until Jetty is shut down.
   * Jetty will check every five seconds for keyboard input from the console, and if it gets some,
   * it will shut down.
   * 
   * @param args If the user specifies a different restURI, dataURI, and/or port number. Any invalid
   * arguments are ignored. If no arguments are overwritten, defaults to public server.
   * @throws Exception If there are any problems.
   */
  public static void main(String[] args) throws Exception {

    // Repeat flags if the user tries to overwrite the same argument.
    Boolean repeatRestURI = false;
    Boolean repeatPort = false;

    // Ensure there is an even amount of arguments.
    if ((args.length % 2) == 0) {

      // Loop through each of the arguments and check if the necessary option is being set.
      for (int i = 0; i < args.length; i = i + 2) {

        // Options that can be set are resturi, and Jetty port number
        if ("-resturi".equalsIgnoreCase(args[i])) {
          // If the user tries to overwrite the RestURI multiple times.
          if (repeatRestURI) {
            System.out.println("Error: RestURI is being configured more than once.");
            System.exit(1);
          }
          // Attempt to make a connection to server.
          // If fail, print an error message and exit the system.
          WattDepotClient client = new WattDepotClient(args[i + 1], null, null);
          
          if (client.isHealthy()) {
            // Set the new rest URI's accordingly.
            MonitorPage.setRestURI(args[i + 1]);
            VisualizationPage.setRestURI(args[i + 1]);
            // Set the repeat value to true if the system tried to overwrite RestURI again.
            repeatRestURI = true;
          }
          else {
            System.out.println("Error: Failed to connect to restURI: " + args[i + 1]);
            System.exit(1);
          }
        }
        else if ("-port".equalsIgnoreCase(args[i])) {
          // If the user tries to overwrite the port again.
          if (repeatPort) {
            System.out.println("Error: Port is being configured more than once.");
            System.exit(1);
          }
          // Ensure the user types in a valid number for the port.
          try {
            int newPort = Integer.parseInt(args[i + 1]);
            // Ensure the number is positive.
            if (newPort >= 0) {
              port = newPort;
              repeatPort = true;
            }
            else {
              System.out.println("Error: Port number is a negative integer.");
              System.exit(1);
            }
          }
          catch (NumberFormatException e) {
            // Print error message and exit program if not an integer.
            System.out.println("Error: Port number is not an integer.");
            System.exit(1);
          }
        }
      }
    }
    else {
      System.out.println("Error: Argument mismatch, number of arguments is not even.");
      System.exit(1);
    }

    Server server = new Server(port);
    Context context = new Context(server, "/" + contextPath, Context.SESSIONS);

    ServletHolder servletHolder = new ServletHolder(new WicketServlet());
    servletHolder.setInitParameter("applicationClassName", applicationClass);
    servletHolder.setInitOrder(1);
    context.addServlet(servletHolder, "/*");
    try {
      server.start();
      // Modify contextPath -> contextPath + "/visualizer" to support a link it provides to
      // visualizer only.
      System.out.printf("%nApplication at http://localhost:%s/%s. Press Return to exit.%n", port,
          contextPath);
      while (System.in.available() == 0) {
        Thread.sleep(5000);
      }
      server.stop();
      server.join();
    }
    catch (Exception e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  /**
   * Connect method to test the connection to a WattDepot Server data source URI.
   * 
   * @param uri contains a string of the URI for the WattDepot data source API to be tested.
   * @return True if connection was successful, false otherwise.
   */
  protected static boolean connectDataSource(String uri) {
    URL url;
    try {
      url = new URL(uri);
    }
    catch (MalformedURLException e) {
      return false;
    }
    URLConnection httpUrl;
    try {
      httpUrl = url.openConnection();
      httpUrl.connect();
    }
    catch (IOException e) {
      return false;
    }
    return true;
  }
}